package com.tengju.user.infrastructure.repository;

import com.tengju.user.domain.model.Row;
import com.tengju.user.domain.model.sign.StarChangeRecordRepository;
import com.tengju.user.domain.model.user.StarChangeEvent;
import com.tengju.user.domain.model.user.StarChangeRecord;
import com.tengju.user.domain.model.user.StarChangeRecordId;
import com.tengju.user.domain.model.user.UserIdCode;
import com.tengju.user.domain.shared.SpringEvent;
import com.tengju.user.infrastructure.persistence.mybatis.dataobject.StarChangeRecordDO;
import com.tengju.user.infrastructure.persistence.mybatis.mapper.dealer.custom.StarChangeRecordDOCustomMapper;
import com.tengju.user.infrastructure.persistence.mybatis.mapper.dealer.generate.StarChangeRecordDOMapper;
import com.tengju.user.infrastructure.persistence.redis.RedisService;
import com.tengju.user.infrastructure.repository.convert.UserConvert;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Repository;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

@Repository
public class StarChangeRecordRepositoryImpl implements StarChangeRecordRepository, ApplicationContextAware {

    @Resource
    StarChangeRecordDOMapper starChangeRecordDOMapper;

    @Resource
    StarChangeRecordDOCustomMapper starChangeRecordDOCustomMapper;

    @Autowired
    RedisService redisService;

    private ApplicationContext applicationContext;

    @Override
    public StarChangeRecord getById(StarChangeRecordId id) {
        StarChangeRecordDO starChangeRecordDO = starChangeRecordDOMapper.selectByPrimaryKey(id.getValue());
        return UserConvert.convertStarChangeRecordDOToEntity(starChangeRecordDO);
    }

    @Override
    public void saveStarChangeRecord(StarChangeRecord starChangeRecord) {
        StarChangeRecordDO starChangeRecordDO = UserConvert.convertStarChangeRecordToDO(starChangeRecord);
        starChangeRecordDOMapper.insertSelective(starChangeRecordDO);
        StarChangeEvent starChangeEvent = new StarChangeEvent(
                starChangeRecord.getIdCode().getValue(),
                starChangeRecord.getBeforeStarLevel(),
                starChangeRecord.getAfterStarLevel(),
                starChangeRecord.getOperBy()
        );
        applicationContext.publishEvent(new SpringEvent(starChangeEvent));
    }

    @Override
    public List<StarChangeRecord> listStarChangeRecord(UserIdCode idCode) {
        if (idCode == null) {
            return Collections.emptyList();
        }
        List<StarChangeRecordDO> starChangeRecordDOS = starChangeRecordDOCustomMapper.listStarChangeRecordByIdCode(idCode.getValue());
        return starChangeRecordDOS.stream()
                .map(UserConvert::convertStarChangeRecordDOToEntity)
                .collect(Collectors.toList());
    }

    @Override
    public List<StarChangeRecord> batchGetLastChangeRecord(List<UserIdCode> idCodes) {
        List<StarChangeRecordDO> starChangeRecordDOList = starChangeRecordDOCustomMapper.batchGetLastChangeRecord(
                idCodes.stream().filter(Objects::nonNull).map(UserIdCode::getValue).collect(Collectors.toList())
        );
        return starChangeRecordDOList.stream()
                .map(UserConvert::convertStarChangeRecordDOToEntity)
                .collect(Collectors.toList());
    }

    @Override
    public List<StarChangeRecord> getStarChangeRecordList(Date startTime, Date endTime) {
        List<StarChangeRecordDO> starChangeRecordDOS = starChangeRecordDOCustomMapper
                .selectStarChangeRecordList(startTime, endTime);
        return starChangeRecordDOS.stream()
                .map(UserConvert::convertStarChangeRecordDOToEntity)
                .collect(Collectors.toList());
    }

    @Override
    public List<Row> signNew(LocalDateTime timeFrom, LocalDateTime timeTo) {
        List<Map<String, Integer>> signNew =
                starChangeRecordDOCustomMapper.signNew(timeFrom, timeTo);
        return signNew.stream().map(Row::new).collect(Collectors.toList());
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
}
